//==============================================================================
//
//  File        : mmpf_display.c
//  Description : Firmware Display Control Function
//  Author      : Penguin Torng
//  Revision    : 1.0
//
//==============================================================================

#include "includes_fw.h"
#include "lib_retina.h"

#include "mmp_reg_display.h"
#include "mmp_reg_video.h"
#include "mmp_reg_ibc.h"
#include "mmp_reg_vif.h"
#include "mmp_reg_gpio.h"
#include "mmp_reg_graphics.h"
#include "mmp_reg_jpeg.h"
//#include "mmp_reg_ccir.h"
#include "mmp_reg_h264enc.h"

#include "mmpf_hif.h"
#include "mmpf_display.h"
#include "mmpf_scaler.h"
#include "mmpf_vif.h"
#if defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(VIDEO_R_EN)
#include "mmpf_mp4venc.h"
#endif
#if defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
#include "mmpf_sensor.h"
#include "mmpf_rawproc.h"
#endif
#if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
#include "mmpf_fdtc.h"
#endif
#if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
#include "mmpf_dma.h"
#endif
#include "mmpf_timer.h"

#if defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
//extern	void VR_3A_SetHardwareBuffer(MMP_ULONG ulStartAddr);
//#include "3A_ctl.h"
#include "isp_if.h"
#endif

#if defined(ALL_FW)
#include "mmps_3gprecd.h"
#include "mmpf_usbpccam.h"
#include "mmpf_usbvend.h"
#include "mmpf_usb_h264.h"
#include "mmpf_usbuvc.h"
#include "mmpf_h264enc.h"
#endif
#include "mmp_reg_dma.h"
#if (SUPPORT_OSD_FUNC)
#include "pCam_osd_api.h"
#endif

#ifdef ZDW_BARCODE
#ifdef ZDW_BARCODE_POWER_ON_WORKING
#include "mmpf_msg.h"
#include "isp_if.h"
extern MMP_BOOL bFirstFrame;
#ifdef ZDW_BARCODE_BTN_USER_MODE
extern MMP_BOOL bAcruiring;
#else
extern MMP_BOOL bScaning;
//extern MMP_BOOL bPowerOnWorking;
#endif
#endif
#endif

//==============================================================================
//
//                              VARIABLES
//
//==============================================================================
#define DBG_H264            0
#if (CHIP == P_V2)
#define	FLM_GPIO_NUM	8  //TBD
#endif
MMP_ULONG   glPreviewBufAddr[MMPF_IBC_PIPE_MAX][4];
MMP_ULONG   glPreviewUBufAddr[MMPF_IBC_PIPE_MAX][4];
MMP_ULONG   glPreviewVBufAddr[MMPF_IBC_PIPE_MAX][4];
MMP_UBYTE   gbPreviewBufferCount[MMPF_IBC_PIPE_MAX];

#if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
#if (defined(ALL_FW)&&(PCAM_EN==0))
MMP_USHORT  gsPreviewBufWidth;              // width of preview buffer
MMP_USHORT  gsPreviewBufHeight;             // height of preview buffer
MMP_ULONG   glRotateBufAddr[2];             // dst Y buffer of rotate DMA
MMP_ULONG   glRotateUBufAddr[2];            // dst U buffer of rotate DMA
MMP_ULONG   glRotateVBufAddr[2];            // dst V buffer of rotate DMA
MMP_UBYTE   gbRotateBufferCount;            // dst buffer count of rotate DMA
//static MMP_USHORT  gsIBCtoDMAPipe = 0;      // keep which pipe links IBC with rotate DMA
MMP_UBYTE   gbRotateDoneBufIdx = 0;         // keep which buffer has the rotated frame
MMP_UBYTE   gbRotateCurBufIdx = 0;          // keep which buffer is to be a dst buffer in turn
#endif
extern MMPF_OS_FLAGID SYS_Flag_Hif;
#endif

#if LCD_DISPLAY_ON==1
MMP_UBYTE   gbExposureDone;
#endif
MMP_UBYTE	gbExposureDoneFrame[MMPF_IBC_PIPE_MAX];
MMP_USHORT	gsPreviewPath;
//MMP_ULONG   glVideoValidFrameCount;
MMP_UBYTE   gbCurIBCBuf[MMPF_IBC_PIPE_MAX];
#ifdef PCCAM_MSB 
MMPF_H264ENC_MSB    gMSB;
#endif
MMP_UBYTE                   gbIBCLinkEncId[MMPF_IBC_PIPE_MAX];
MMPF_IBC_LINK_TYPE			gIBCLinkType[MMPF_IBC_PIPE_MAX];
//MMPF_DISPLAY_PREVIEW_MODE	gPreviewMode[2];
//MMPF_DISPLAY_WINID			gPreviewWinID[2];

//MMPF_OS_SEMID   m_PreviewControlSem;
//MMPF_OS_SEMID   m_StartPreviewFrameEndSem;

#if DRAM_SIZE <= 2
volatile MMP_BOOL gbIBCWritting;
/*MMP_BOOL gbHDmode;*/ /*if the resolution <= VGA, FPS == 30, set gbHDmode to 0
                                       <= 800x600, FPS = 15, set to 1
                                       <= HD, FPS == 10, set to 2
                                       > HD, not supported                 */
#endif

//static MMP_BOOL		m_bReceiveStopPreviewSig[MMPF_IBC_PIPE_MAX];
//static MMP_BOOL		m_bStartPreviewFrameEndSig;
//static MMP_BOOL		m_bWaitVIFEndSig = MMP_FALSE;

#if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
extern MMP_BOOL         gbFWDrawFaceRect;
extern MMP_BOOL         gbInFDTCMode;
extern MMPF_OS_FLAGID 	FDTC_Flag;
#endif

#if defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
extern	MMP_USHORT	m_gsISPCoreID;
extern	MMPF_SENSOR_FUNCTION *gsSensorFunction;
#endif

extern  MMP_ULONG   glSystemEvent;

#if defined(ALL_FW)
extern MMP_ULONG   glPccamResolution;
extern void MMPF_USB_ReleaseDm(MMP_UBYTE pipe);
//extern volatile MMP_UBYTE usb_fb_toggle;
extern MMP_ULONG   glPCCamCompressBufAddr;
extern MMP_ULONG glPCCamCnt;
extern MMPS_3GPRECD_VIDEO_FORMAT m_VideoFmt;
//extern MMP_UBYTE gbStillCaptureEvent;
//extern MMP_ULONG glPCCAM_VIDEO_BUF_ADDR;
extern MMP_ULONG glPCCAM_VIDEO_BUF_MAX_SIZE;
extern MMP_USHORT      gsVidRecdStatus;                    // tomy@2011_02_25
#endif

extern H264_FORMAT_TYPE gbCurH264Type;
//extern MMP_UBYTE gbUsbVideoSel;
#if (SUPPORT_OSD_FUNC)
extern MMP_BYTE 		strTimeDate[];
MMP_ULONG OSD_CurrentW[MMPF_IBC_PIPE_MAX],OSD_CurrentH[MMPF_IBC_PIPE_MAX];
MMP_ULONG OSD_FontW[MMPF_IBC_PIPE_MAX],OSD_FontH[MMPF_IBC_PIPE_MAX];
#endif

extern MMP_ULONG gljpeg_en_start_time;

//==============================================================================
//
//                              FUNCTION PROTOTYPES
//
//==============================================================================
void MMPF_Display_LoobackMJPEGFrame(MMPF_GRAPHICS_RECT 			*Rect,
                                    GraphicRotDMACallBackFunc 	*GraEndCallback,
                                    MMP_ULONG                   SrcAddr,
                                    MMP_UBYTE  					ubSrcIBCPipeNum);
void MMPF_Display_LoobackYUVFrame(MMPF_GRAPHICS_RECT *Rect,
                                  GraphicRotDMACallBackFunc *GraEndCallback,
                                  MMP_ULONG SrcAddr,
                                  MMP_UBYTE ubSrcIBCPipeNum);

MMPF_GRAPHICS_BUFATTRIBUTE  m_GraSrcBufAttr = 
{
	0, 0,   //width, height
	0,      //line offset
	MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE,
	0, 0, 0 //YUV buf addr
};

MMPF_GRAPHICS_RECT  m_GraRect = 
{
	0, 0,   //top,   left
	0, 0    //width, height
};

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_GpioISR
//  Description :
//------------------------------------------------------------------------------
void MMPF_Display_GpioISR(void)
{
	AITPS_GPIO   pGPIO  = AITC_BASE_GPIO;
	
	//MMP_USHORT	ibc_pipID, i;
	
	MMP_ULONG	intsrc0, intsrc1;
	//MMP_ULONG	gpio_shift;
	//MMP_ULONG	gpio_group;
	#if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
    //MMP_UBYTE   rotbufIdx; 
	#endif    

	intsrc0 = pGPIO->GPIO_INT_L2H_STS[0] & pGPIO->GPIO_INT_CPU_EN[0];
	pGPIO->GPIO_INT_L2H_STS[0] = intsrc0;

	intsrc1 = pGPIO->GPIO_INT_L2H_STS[1] & pGPIO->GPIO_INT_CPU_EN[1];
	pGPIO->GPIO_INT_L2H_STS[1] = intsrc1;

/*
	gpio_shift = FLM_GPIO_NUM;

	gpio_group = 0;
	while (gpio_shift >= 32) {
		gpio_shift -= 32;
		gpio_group += 1;
	}

	if (gpio_group) {
		intsrc = pGPIO->GPIO_INT_L2H_STS[gpio_group] & pGPIO->GPIO_INT_CPU_EN[gpio_group];
		pGPIO->GPIO_INT_L2H_STS[gpio_group] = intsrc;
	}		
*/
	
#if 1  // for key button event
/*
#if (CUSTOMER == NMG)  
    if(intsrc0 & (1 << SNAP_PIN)) {
        glSystemEvent |= SNAP_BUTTON_PRESSED;
        MMPF_OS_SetFlags(SYS_Flag_Hif,SYS_FLAG_USBOP, MMPF_OS_FLAG_SET);
        RTNA_DBG_Str(0, "SNAP_BUTTON\r\n");
    }
    if(intsrc0 & (1 << FLIP_PIN)) {
        glSystemEvent |= FLIP_BUTTON_PRESSED;
        MMPF_OS_SetFlags(SYS_Flag_Hif,SYS_FLAG_USBOP, MMPF_OS_FLAG_SET);
        RTNA_DBG_Str(0, "FLIP_BUTTON\r\n");
    }
    if(intsrc1 & (1 << (IRHID_PIN-32))) {
        glSystemEvent |= IRHID_BUTTON_PRESSED;
        MMPF_OS_SetFlags(SYS_Flag_Hif,SYS_FLAG_USBOP, MMPF_OS_FLAG_SET);
        RTNA_DBG_Str(0, "IRHID_BUTTON\r\n");
    }
#endif
*/

#else	
	
	if (intsrc & (1 << gpio_shift)) {
	    if (gsPreviewPath == 0) {
	        #if	defined(VIDEO_AMR_P_FW)||defined(VIDEO_AAC_P_FW)||defined(AVI_MP3_P_FW)||(VIDEO_P_EN)
	        MMPF_VPP_RefreshFrame();
	        #endif
	    }
	    else {
    		if (gbExposureDone) {
    			gbExposureDone = 0;
                
				#if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
				if (gIBCLinkType[gsIBCtoDMAPipe] & MMPF_IBC_LINK_ROTATE) {              
                    rotbufIdx = (gbRotateDoneBufIdx == 0) ? gbRotateBufferCount-1 : gbRotateDoneBufIdx-1;
                    MMPF_Display_SetWinAddr(gPreviewWinID[gsIBCtoDMAPipe], glRotateBufAddr[rotbufIdx],
        					    glRotateUBufAddr[rotbufIdx], glRotateVBufAddr[rotbufIdx]);
                    MMPF_Display_SetWinActive(gPreviewWinID[gsIBCtoDMAPipe], MMP_TRUE);
                }
    			else {
    				for (i = 0; i < 2; i++) {
    					if (gPreviewMode[i] == MMPF_DISPLAY_FLM && (gsPreviewPath & (1 << i))) {
    						ibc_pipID = i;
    					}
    				}

    	        	MMPF_Display_SetWinAddr(gPreviewWinID[ibc_pipID],
    	        				glPreviewBufAddr[ibc_pipID][gbExposureDoneFrame[ibc_pipID]],
    	        				glPreviewUBufAddr[ibc_pipID][gbExposureDoneFrame[ibc_pipID]],
    	        				glPreviewVBufAddr[ibc_pipID][gbExposureDoneFrame[ibc_pipID]]);
    				MMPF_Display_SetWinActive(gPreviewWinID[ibc_pipID], MMP_TRUE);
    			}
				#else
    			for (i = 0; i < 2; i++) {
    				if (gPreviewMode[i] == MMPF_DISPLAY_FLM && (gsPreviewPath & (1 << i))) {
    					ibc_pipID = i;
    				}
    			}

            	MMPF_Display_SetWinAddr(gPreviewWinID[ibc_pipID], 
            				glPreviewBufAddr[ibc_pipID][gbExposureDoneFrame[ibc_pipID]],
            				glPreviewUBufAddr[ibc_pipID][gbExposureDoneFrame[ibc_pipID]],
            				glPreviewVBufAddr[ibc_pipID][gbExposureDoneFrame[ibc_pipID]]);
    			MMPF_Display_SetWinActive(gPreviewWinID[ibc_pipID], MMP_TRUE);
				#endif

                if (gPreviewWinID[ibc_pipID] == MMPF_DISPLAY_WIN_SCD_WIN) {
            	    MMPF_Display_SetRefresh(MMPF_DISPLAY_SCD_CONTROL);
                }
                else {
            	    MMPF_Display_SetRefresh(MMPF_DISPLAY_PRM_CONTROL);
                }
    		}
		}
	}
#endif	
}

#if (defined(ALL_FW)&&(PCAM_EN==0))
//------------------------------------------------------------------------------
//  Function    : MMPF_Display_ISR
//  Description :
//------------------------------------------------------------------------------
void MMPF_Display_ISR(void)
{
    AITPS_DSPY  pDSPY    = AITC_BASE_DSPY;
	MMP_USHORT	intsrc;

	intsrc = pDSPY->DSPY_INT_CPU_EN & pDSPY->DSPY_INT_CPU_SR;
	pDSPY->DSPY_INT_CPU_SR = intsrc;
}
#endif

#if EN_TIME_LOG
extern TIME_LOG tlWr0, tlH264, tlRd0, tlWr0S;
#endif

#if RAW_DATA_EN
MMP_ERR MMPF_RawG_To_YData(MMP_UBYTE *bSrcPtr, MMP_ULONG ulSrcWidth, MMP_ULONG ulSrcHeight,
                           MMP_UBYTE *bDstPtr, MMP_ULONG ulDstWidth, MMP_ULONG ulDstHeight)
{
    MMP_ULONG i = 0;
    MMP_ULONG j = 0;
    MMP_UBYTE *bDTCMbuf = (MMP_UBYTE *)0x80000;

    #if 0 //timing measure
    MMP_ULONG ulTick0 = 0;
    MMP_ULONG ulTick1 = 0;
    ulTick0 = OSTimeGet();
    #endif
    
    #if RAW_PROC_10_BIT_EN
    #error The function only support 8bit raw data.
    #endif

    ulDstWidth = ulDstWidth >> 1;
    for (i = 0; i < ulDstHeight; i += 2) {
        if(ulSrcWidth==240)
            bSrcPtr += 40;

        bDTCMbuf = (MMP_UBYTE *)0x80000;
        MEMCPY(bDTCMbuf, bSrcPtr, ulSrcWidth);
        for (j = 0; j < ulDstWidth; j++) {
            if (*(bDTCMbuf + 1) < 150)
                *(bDTCMbuf + 1) = (*(bDTCMbuf + 1) * 3) >> 2;

            *bDTCMbuf = *(bDTCMbuf + 1);
            bDTCMbuf += 2;
        }
        bDTCMbuf = (MMP_UBYTE *)0x80000;
        MEMCPY(bDstPtr, bDTCMbuf, ulSrcWidth);
        bSrcPtr += ulSrcWidth;
        bDstPtr += ulDstWidth << 1;

        if(ulSrcWidth==240)
            bSrcPtr += 80;

        MEMCPY(bDTCMbuf, bSrcPtr, ulSrcWidth);
        for (j = 0; j < ulDstWidth; j++) {
            if (*(bDTCMbuf) < 150)
                *(bDTCMbuf) = (*(bDTCMbuf) * 3) >> 2;

            *(bDTCMbuf + 1) = *bDTCMbuf;
            bDTCMbuf += 2;
        }
        bDTCMbuf = (MMP_UBYTE *)0x80000;
        MEMCPY(bDstPtr, bDTCMbuf, ulSrcWidth);
        bSrcPtr += ulSrcWidth;
        bDstPtr += ulDstWidth << 1;
        
        if(ulSrcWidth==240)
            bSrcPtr += 40;
    }

    #if 0 //timing measure
    ulTick1 = OSTimeGet();
    RTNA_DBG_Str(0, "T:");
    RTNA_DBG_Long(0, ulTick1 - ulTick0);
    RTNA_DBG_Str(0, "\r\n");
    #endif

    #if 0//SUPPORT_PIPE_Y
    {
        extern MMP_USHORT MD_x_res, MD_y_res;
        MMP_ULONG jpegSize, buf_addr;
        FRAME_PAYLOAD_HEADER *yuv_ph;

        buf_addr = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_Y);
        yuv_ph = (FRAME_PAYLOAD_HEADER *) buf_addr;
        jpegSize = MD_x_res*MD_y_res;
        usb_fill_payload_header((MMP_UBYTE *)buf_addr,jpegSize,glPCCamCnt,0,3,MD_x_res,MD_y_res, ISP_IF_AE_GetRealFPS(), ST_Y, PIPE_Y);
        MMPF_USB_ReleaseDm(PIPE_Y);
    }
    #endif

    return MMP_ERR_NONE;
}
#endif

extern MMP_UBYTE gbGraphicLoopBackSource;
extern MMP_ULONG glGraphicLoopBackCnt;
extern MMP_UBYTE gbGraLBEvent;

#if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
extern MMP_ULONG glOSDBufferYAddr[], glOSDBufferUVAddr[];
extern MMPF_DMA_M_LOFFS_DATA    gOSDFrameOffset;
extern MMP_USHORT m_usOsdStartXOffset, m_usOsdStartYoffset;
extern MMP_USHORT gsOSDLineNum;
#endif

#if (SUPPORT_OSD_FUNC)
extern MMP_USHORT gsOSD_WIDTH_MAX_WORD;
#endif

MMP_ULONG glCurYBufAddr0, glCurYBufAddr1;
#if (SUPPORT_OSD_FUNC)
MMP_BOOL  gbOSDDisplayEn = 1;
#else
MMP_BOOL  gbOSDDisplayEn = 0;
#endif

void RotateDma0UVCallBack(void)
{
    MMP_UBYTE release = 1 ;

    //dbg_printf(3, "R0 UV done\r\n");
    if(((gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG)) &&
       (gbGraphicLoopBackSource == PIPE_0)){
        #if (MJPG_FPS_CTL == 1)
        release = CheckMJPGFrameDrop();
        #endif
        if((gbGraLBEvent) && (release == 1)){
            glGraphicLoopBackCnt++;
            MMPF_Display_LoobackMJPEGFrame(NULL, NULL, glCurYBufAddr0, MMPF_IBC_PIPE_0);
            gbGraLBEvent = 0;
            //dbg_printf(3, "GlbP2[x%X]\r\n", glCurYBufAddr0);                        
        }
    }
#if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
    MMPF_Display_FrameDoneTrigger(0);
#endif
}

void MoveDma0UVCallBack(void)
{
    //dbg_printf(3, "M0 UV done\r\n");
    if(((gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG)) &&
       (gbGraphicLoopBackSource == PIPE_1)){
        MMP_UBYTE release;
        #if (MJPG_FPS_CTL == 1)
        release = CheckMJPGFrameDrop();
        #else
        release = 1;
        #endif
        if((gbGraLBEvent) && (release == 1)){
            glGraphicLoopBackCnt++;
            MMPF_Display_LoobackMJPEGFrame(NULL, NULL, glCurYBufAddr1, MMPF_IBC_PIPE_1);
            gbGraLBEvent = 0;
            //dbg_printf(3, "GlbP2[x%X]\r\n", y_buf_addr);                        
        }
    }
#if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
    if((gbCurH264Type==FRAMEBASE_DUAL_H264) || (gbCurH264Type==FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type==FRAMEBASE_H264RT_MJPEG) || (gbCurH264Type==FRAMEBASE_H264)){
        MMPF_Display_FrameDoneTrigger(1);
    }
    #if (SUPPORT_H264MV_MD)
    else if(gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG){
        // check if support motion vector mode
        MMPF_VIDENC_FILTER_MODE FilterMode;
        MMPF_VIDENC_GetParameter(1, MMPF_VIDENC_ATTRIBUTE_FILTER_MODE, (void*)&FilterMode);
        if (FilterMode != MMPF_VIDENC_FILTER_ENCODER){
            MMPF_Display_FrameDoneTrigger(1);
            //dbg_printf(3, "MV Trig\r\n");
        }
    }
    #endif
#endif
}

#if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
MMP_ULONG glCurUVBufAddr0, glCurUVBufAddr1;

void RotateDma0YCallBack(void)
{
    //dbg_printf(3, "R0 Y done\r\n");
        // using Rotate DMA0 to transfer OSD UV buffer 0
    MMPF_DMA_RotateData0(glOSDBufferUVAddr[0], glCurUVBufAddr0, (gsOSD_WIDTH_MAX_WORD*OSD_FontW[0]), OSD_CurrentW[0], gsOSD_WIDTH_MAX_WORD*OSD_FontW[0], OSD_FontH[0]*gsOSDLineNum/2, 
                         DMA_R_BPP_8 | DMA_R_BLK_16X16, DMA_R_MIRROR_DISABLE, RotateDma0UVCallBack);
}

void MoveDma0YCallBack(void)
{
    //dbg_printf(3, "M0 Y done\r\n");
    // using MOVE DMA0 to transfer OSD UV buffer 1
    gOSDFrameOffset.SrcWidth = gsOSD_WIDTH_MAX_WORD*OSD_FontW[1];
    gOSDFrameOffset.SrcOffset = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);
    gOSDFrameOffset.DstWidth = gsOSD_WIDTH_MAX_WORD*OSD_FontW[1];
    gOSDFrameOffset.DstOffset = OSD_CurrentW[1];
    MMPF_DMA_MoveData0(glOSDBufferUVAddr[1], glCurUVBufAddr1, gOSDFrameOffset.SrcWidth*OSD_FontH[1]*gsOSDLineNum/2, &gOSDFrameOffset, MoveDma0UVCallBack);
}

MMP_ULONG glOSDBufferUAddr;
void MoveDma0CallBack(void)
{
    MMP_ULONG   DMASrcAddr, DMADestAddr;

    DMASrcAddr = glOSDBufferYAddr[1];
#if (OSD_DISPLAY_ON_UP_RIGHT)
    DMADestAddr = glCurYBufAddr1 + (m_usOsdStartYoffset * OSD_CurrentW[1]) + (OSD_CurrentW[1] - m_usOsdStartXOffset - gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);  
    glCurUVBufAddr1 = glOSDBufferUAddr + (m_usOsdStartYoffset * OSD_CurrentW[1] / 2) + (OSD_CurrentW[1] - m_usOsdStartXOffset - gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);
#else
    DMADestAddr = glCurYBufAddr1 + (m_usOsdStartYoffset * OSD_CurrentW[1]) + m_usOsdStartXOffset;  
    glCurUVBufAddr1 = glOSDBufferUAddr + (m_usOsdStartYoffset * OSD_CurrentW[1] / 2) + m_usOsdStartXOffset; 
#endif

    // using MOVE DMA0
    gOSDFrameOffset.SrcWidth = gsOSD_WIDTH_MAX_WORD*OSD_FontW[1];
    gOSDFrameOffset.SrcOffset = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);
    gOSDFrameOffset.DstWidth = gsOSD_WIDTH_MAX_WORD*OSD_FontW[1];
    gOSDFrameOffset.DstOffset = OSD_CurrentW[1];
    MMPF_DMA_MoveData0(DMASrcAddr, DMADestAddr, gOSDFrameOffset.SrcWidth*OSD_FontH[1]*gsOSDLineNum, &gOSDFrameOffset, MoveDma0YCallBack);
}
#endif
#if SUPPORT_AIT845x_MD
void MoveDmaYCallBack(void)
{
    extern MMPF_OS_FLAGID AIT845xMD_Flag;
    extern MMP_ULONG gbMDaddr;

    gbMDaddr = (MMP_ULONG)((MMP_UBYTE*)(MMPF_Video_CurWrPtr(PIPE_G) + FRAME_PAYLOAD_HEADER_SZ));
    MMPF_OS_SetFlags(AIT845xMD_Flag, MD_FLAG_AIT845xMD, MMPF_OS_FLAG_SET);
}
#endif
extern void MMPF_Sensor_SetSensorShutter_CG2355K(MMP_ULONG dir, MMP_ULONG vsync);

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_IbcISR
//  Description : 
//------------------------------------------------------------------------------
void MMPF_Display_IbcISR(void)
{
    extern MMP_ULONG PTS;
    extern IbcCallBackFunc *CallBackFuncIbc[MMPF_IBC_EVENT_MAX][MMPF_IBC_PIPE_MAX];
  
    AITPS_IBC   pIBC    = AITC_BASE_IBC;
    MMP_UBYTE	intsrc0, intsrc1, intsrc2;
    MMP_ULONG   jpegSize, buf_addr;
    MMP_UBYTE   yuv_en = 0 ;
    PIPE_PATH   yuv_pipe = PIPE_Error ;
    MMP_UBYTE   pipe0_cfg, pipe1_cfg, pipe2_cfg;
    FRAME_PAYLOAD_HEADER 	    *yuv_ph; 	
    volatile AITPS_IBCP pIbcPipeCtl;
#if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
    MMP_ULONG   DMASrcAddr, DMADestAddr;
#endif
    
    const STREAM_CFG *stream_cfg = usb_get_stream_cfg();
    
    intsrc0 = pIBC->IBC_P0_INT_CPU_EN & pIBC->IBC_P0_INT_CPU_SR;
    pIBC->IBC_P0_INT_CPU_SR = intsrc0;

    intsrc1 = pIBC->IBC_P1_INT_CPU_EN & pIBC->IBC_P1_INT_CPU_SR;
    pIBC->IBC_P1_INT_CPU_SR = intsrc1;

    intsrc2 = pIBC->IBC_P2_INT_CPU_EN & pIBC->IBC_P2_INT_CPU_SR;
    pIBC->IBC_P2_INT_CPU_SR = intsrc2;

    pipe0_cfg = GET_PIPE_FORMAT(stream_cfg, 0);
    pipe1_cfg = GET_PIPE_FORMAT(stream_cfg, 1);
    pipe2_cfg = GET_PIPE_FORMAT(stream_cfg, 2);
    //RTNA_DBG_Str3("IBC.S\r\n");

    if(intsrc0 & (IBC_INT_FRM_RDY | IBC_INT_PRE_FRM_RDY)) 
    {
        if(stream_cfg->pipe_en&PIPE0_EN) {
            if( (pipe0_cfg==PIPE_CFG_YUY2) || (pipe0_cfg==PIPE_CFG_NV12) ) {
                yuv_en = 1 ;
                if (IS_PIPE_RING(stream_cfg, 0)) {
                    if (intsrc0 & IBC_INT_FRM_RDY) {
                        yuv_en = 0;
                        gbIBCWritting = MMP_FALSE;
                        MMPF_Timer_Log(&tlWr0);
                        //DBG_SMALL_TAG("D");//IBC 'D'one
                    } else {
                        //DBG_S(3, "D");
                        gbIBCWritting = MMP_TRUE;
                        //DBG_SMALL_TAG("P"); // 'P're-frame ready
                    }
                }
            } else if((pipe0_cfg==PIPE_CFG_H264) && (intsrc0 & IBC_INT_FRM_RDY)) {
                //RTNA_DBG_Str3("IBC.0\r\n");
                yuv_en = 0 ;
                if(gsVidRecdStatus == MMPF_MP4VENC_FW_STATUS_START){  // tomy@2011_02_25, to fix the corrupted 1st frame in every H.264 transmission

                    pIbcPipeCtl = &(pIBC->IBCP_0);
                    glCurYBufAddr0 = pIbcPipeCtl->IBC_ADDR_Y_ST;
                    
        #if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
                    if (gbOSDDisplayEn == 1) {
                        DMASrcAddr = glOSDBufferYAddr[0];
            #if (OSD_DISPLAY_ON_UP_RIGHT)
                        DMADestAddr = glCurYBufAddr0 + (m_usOsdStartYoffset * OSD_CurrentW[0]) + (OSD_CurrentW[0] - m_usOsdStartXOffset - gsOSD_WIDTH_MAX_WORD*OSD_FontW[0]);  
                        glCurUVBufAddr0 = pIbcPipeCtl->IBC_ADDR_U_ST + (m_usOsdStartYoffset * OSD_CurrentW[0] / 2) + (OSD_CurrentW[0] - m_usOsdStartXOffset - gsOSD_WIDTH_MAX_WORD*OSD_FontW[0]);
            #else
                        DMADestAddr = glCurYBufAddr0 + (m_usOsdStartYoffset * OSD_CurrentW[0]) + m_usOsdStartXOffset;  
                        glCurUVBufAddr0 = pIbcPipeCtl->IBC_ADDR_U_ST + (m_usOsdStartYoffset * OSD_CurrentW[0] / 2) + m_usOsdStartXOffset;
            #endif 

                        // using Rotate DMA0
                        MMPF_DMA_RotateData0(DMASrcAddr, DMADestAddr, (gsOSD_WIDTH_MAX_WORD*OSD_FontW[0]), OSD_CurrentW[0], gsOSD_WIDTH_MAX_WORD*OSD_FontW[0], OSD_FontH[0]*gsOSDLineNum, 
                                             DMA_R_BPP_8 | DMA_R_BLK_16X16, DMA_R_MIRROR_DISABLE, RotateDma0YCallBack);
                    } else if(((gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG)) &&
                            (gbGraphicLoopBackSource == PIPE_0)){
                    } else
        #endif
                    {
                        MMPF_Display_FrameDoneTrigger(0); 
                    }
                    //dbg_printf(3, "P0[%d]\r\n", gbGraLBEvent);

        #if (MOVE_OSD_USING_DMA)
                    if(gbOSDDisplayEn == 0)
        #endif                     
                    {
                        RotateDma0UVCallBack();  // trigger loop back MJPG encoding
                    }
                }
            }
        }    
        
        if(yuv_en) {
            yuv_pipe = PIPE_0 ;
            //RTNA_DBG_Str3("IBC.0\r\n");
        }
    }

#if Y_DATA_EN && SUPPORT_AIT845x_MD
    if (intsrc1 & IBC_INT_PRE_FRM_RDY) {
        if((gbCurH264Type==FRAMEBASE_DUAL_H264_MJPEG)&&(gbGraphicLoopBackSource==PIPE_1)) {
            pIbcPipeCtl = &(pIBC->IBCP_1);
            glGraphicLoopBackCnt++;
            MMPF_Display_LoobackYUVFrame(NULL, NULL, pIbcPipeCtl->IBC_ADDR_Y_ST, MMPF_IBC_PIPE_1);
        }
        if(gbCurH264Type==FRAMEBASE_H264FRAME_MJPEG) {
            MMPF_DMA_M_LOFFS_DATA y;
            MMP_ULONG destaddr;
            pIbcPipeCtl = &(pIBC->IBCP_1);

            destaddr = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_G);
            if((glPCCamCnt%6)==0){
            //MMP_ULONG ysize = PIPE_INFO(1,w)*PIPE_INFO(1,h);
            //usb_fill_payload_header((MMP_UBYTE *)destaddr,ysize,glPCCamCnt,0,PTS,PIPE_INFO(1,w),PIPE_INFO(1,h), ISP_IF_AE_GetRealFPS(), ST_Y, PIPE_G);
            // using MOVE DMA0
            y.SrcWidth  = PIPE_INFO(1,w);
            y.SrcOffset = PIPE_INFO(1,w);
            y.DstWidth  = PIPE_INFO(1,w);
            y.DstOffset = PIPE_INFO(1,w);
            MMPF_DMA_MoveData0(pIbcPipeCtl->IBC_ADDR_Y_ST, destaddr + FRAME_PAYLOAD_HEADER_SZ, PIPE_INFO(1,w)*PIPE_INFO(1,h), &y, MoveDmaYCallBack);
            MMPF_Video_UpdateWrPtr(PIPE_G);
            }
        }
        //RTNA_DBG_Str3("preIBC.1\r\n");
    }
#endif

    if(intsrc1 & IBC_INT_FRM_RDY) {	    	
        //RTNA_DBG_Str3("IBC.1\r\n");
        if(stream_cfg->pipe_en&PIPE1_EN) {
            if( (pipe1_cfg==PIPE_CFG_YUY2) || (pipe1_cfg==PIPE_CFG_NV12) ) {
                yuv_en = 1 ;
            } else if(pipe1_cfg==PIPE_CFG_H264) {
                yuv_en = 0;
                if(gsVidRecdStatus == MMPF_MP4VENC_FW_STATUS_START){  // tomy@2011_02_25, to fix the corrupted 1st frame in every H.264 transmission

                    pIbcPipeCtl = &(pIBC->IBCP_1);
                    glCurYBufAddr1 = pIbcPipeCtl->IBC_ADDR_Y_ST;
                    
                    #if Y_DATA_EN && !SUPPORT_AIT845x_MD
                    if(gbCurH264Type==FRAMEBASE_DUAL_H264_MJPEG) {
                        MMPF_DMA_M_LOFFS_DATA y;
                        MMP_ULONG ysize = PIPE_INFO(1,w)*PIPE_INFO(1,h), destaddr;

                        destaddr = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_G);
                        usb_fill_payload_header((MMP_UBYTE *)destaddr,ysize,glPCCamCnt,0,PTS,PIPE_INFO(1,w),PIPE_INFO(1,h), ISP_IF_AE_GetRealFPS(), ST_Y, PIPE_G);

                        // using MOVE DMA0
                        y.SrcWidth  = PIPE_INFO(1,w);
                        y.SrcOffset = PIPE_INFO(1,w);
                        y.DstWidth  = PIPE_INFO(1,w);
                        y.DstOffset = PIPE_INFO(1,w);
                        #if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
                        if(gbOSDDisplayEn) {
                            glOSDBufferUAddr = pIbcPipeCtl->IBC_ADDR_U_ST;
                            MMPF_DMA_MoveData0(pIbcPipeCtl->IBC_ADDR_Y_ST, destaddr + FRAME_PAYLOAD_HEADER_SZ, PIPE_INFO(1,w)*PIPE_INFO(1,h), &y, MoveDma0CallBack);
                        } else
                        #endif
                            MMPF_DMA_MoveData0(pIbcPipeCtl->IBC_ADDR_Y_ST, destaddr + FRAME_PAYLOAD_HEADER_SZ, PIPE_INFO(1,w)*PIPE_INFO(1,h), &y, MoveDma0UVCallBack);

                        MMPF_Video_UpdateWrPtr(PIPE_G);
                    } else
                    #else
        #if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
                    if (gbOSDDisplayEn == 1) {
                        DMASrcAddr = glOSDBufferYAddr[1];
            #if (OSD_DISPLAY_ON_UP_RIGHT)
                        DMADestAddr = glCurYBufAddr1 + (m_usOsdStartYoffset * OSD_CurrentW[1]) + (OSD_CurrentW[1] - m_usOsdStartXOffset - gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);  
                        glCurUVBufAddr1 = pIbcPipeCtl->IBC_ADDR_U_ST + (m_usOsdStartYoffset * OSD_CurrentW[1] / 2) + (OSD_CurrentW[1] - m_usOsdStartXOffset - gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);
            #else
                        DMADestAddr = glCurYBufAddr1 + (m_usOsdStartYoffset * OSD_CurrentW[1]) + m_usOsdStartXOffset;  
                        glCurUVBufAddr1 = pIbcPipeCtl->IBC_ADDR_U_ST + (m_usOsdStartYoffset * OSD_CurrentW[1] / 2) + m_usOsdStartXOffset; 
            #endif

                        // using MOVE DMA0
                        gOSDFrameOffset.SrcWidth = gsOSD_WIDTH_MAX_WORD*OSD_FontW[1];
                        gOSDFrameOffset.SrcOffset = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]);
                        gOSDFrameOffset.DstWidth = gsOSD_WIDTH_MAX_WORD*OSD_FontW[1];
                        gOSDFrameOffset.DstOffset = OSD_CurrentW[1];
                        MMPF_DMA_MoveData0(DMASrcAddr, DMADestAddr, gOSDFrameOffset.SrcWidth*OSD_FontH[1]*gsOSDLineNum, &gOSDFrameOffset, MoveDma0YCallBack);
                    } else
        #endif
                    #endif
                    {
                        if((gbCurH264Type==FRAMEBASE_DUAL_H264) || (gbCurH264Type==FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type==FRAMEBASE_H264RT_MJPEG) || (gbCurH264Type==FRAMEBASE_H264)){
                            MMPF_Display_FrameDoneTrigger(1);
                        }
                        #if (SUPPORT_H264MV_MD)
                        else if(gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG){
                            // check if support motion vector mode
                            MMPF_VIDENC_FILTER_MODE FilterMode;
                            MMPF_VIDENC_GetParameter(1, MMPF_VIDENC_ATTRIBUTE_FILTER_MODE, (void*)&FilterMode);
                            if (FilterMode != MMPF_VIDENC_FILTER_ENCODER){
                                MMPF_Display_FrameDoneTrigger(1);
                                //dbg_printf(3, "MV Trig\r\n");
                            }
                        }
                        #endif
                    }
                    //dbg_printf(3, "P1[%d]   \r\n", gbGraLBEvent);
                    
        #if (MOVE_OSD_USING_DMA)
                    if(gbOSDDisplayEn == 0) 
        #endif
                    {
                        MoveDma0UVCallBack();  // trigger loop back MJPG encoding
                    }
                }
            }
        }    
        
        if(yuv_en) {
            yuv_pipe = PIPE_1 ;
            //RTNA_DBG_Str3("IBC.1\r\n");
        }
    }
    
    if (intsrc2 & IBC_INT_FRM_RDY) {
        if(stream_cfg->pipe_en&PIPE2_EN) {
            if( (pipe2_cfg==PIPE_CFG_YUY2) || (pipe2_cfg==PIPE_CFG_NV12) ) {
                yuv_en = 1 ;
            }
            #if Y_DATA_EN && SUPPORT_AIT845x_MD
            else if(pipe2_cfg==PIPE_CFG_MJPEG) {
                yuv_en = 0;

                if(gbCurH264Type==FRAMEBASE_DUAL_H264_MJPEG) {
                    MMP_ULONG ysize = 320*180;
                    extern MMPF_OS_FLAGID AIT845xMD_Flag;
                    extern MMP_ULONG gbMDaddr;

                    gbMDaddr = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_G);
                    MMPF_OS_SetFlags(AIT845xMD_Flag, MD_FLAG_AIT845xMD, MMPF_OS_FLAG_SET);

                    usb_fill_payload_header((MMP_UBYTE *)gbMDaddr,ysize,glPCCamCnt,0,PTS,320,180, ISP_IF_AE_GetRealFPS(), ST_Y, PIPE_G);
                    MMPF_Video_UpdateWrPtr(PIPE_G);
                }
                //dbg_printf(3, "MD trigger\r\n");
            }
            #endif
        }    
        
        if(yuv_en) {
            yuv_pipe = PIPE_2;
            RTNA_DBG_Str3("IBC.2\r\n");
        }
    }
    
#if PCAM_EN==1    
    if( yuv_pipe != PIPE_Error) {
        MMP_UBYTE release = 1 ;
        volatile AITPS_IBCP pIbcPipeCtl;

        if (yuv_pipe == PIPE_0) {
            pIbcPipeCtl = &(pIBC->IBCP_0);
        }
        else if (yuv_pipe == PIPE_1) {
            pIbcPipeCtl = &(pIBC->IBCP_1);
        }
        else {
            pIbcPipeCtl = &(pIBC->IBCP_2);
        }

        if ((pIbcPipeCtl->IBC_BUF_CFG & IBC_RING_BUF_EN) == 0) {
            pIbcPipeCtl->IBC_BUF_CFG &= ~(IBC_STORE_EN);
        }

        if( (stream_cfg->pipe_en&PIPE_EN_MASK)==(PIPE0_EN|PIPE1_EN) ) {
            if((pipe1_cfg == PIPE_CFG_H264) || (pipe0_cfg == PIPE_CFG_H264)) {
                release = 0 ;
            }
        }
        // Get cur slot addr 
        buf_addr = (MMP_ULONG)MMPF_Video_CurWrPtr(yuv_pipe);
        yuv_ph = (FRAME_PAYLOAD_HEADER *) buf_addr;

        jpegSize = GetYUY2FrameSize(glPccamResolution);
        glPCCamCnt++ ;

        if(PH_GET_TX_CTL(yuv_ph->FRAME_H264_PH.dwFlag) == 0){
            usb_fill_payload_header((MMP_UBYTE *)buf_addr,jpegSize,glPCCamCnt,0,PTS,PIPE_INFO(yuv_pipe,w),PIPE_INFO(yuv_pipe,h), ISP_IF_AE_GetRealFPS(), ST_YUY2, yuv_pipe);
        }
        
        #if 0
        RTNA_DBG_Str3("-glPCCamCnt:");
        RTNA_DBG_Long3(glPCCamCnt);
        RTNA_DBG_Str3(" :  buf_addr:");
        RTNA_DBG_Long3(buf_addr);
        RTNA_DBG_Str3("\r\n");
        #endif

        if ((pIbcPipeCtl->IBC_BUF_CFG & IBC_RING_BUF_EN) == 0) {
            if(release) {
                MMPF_USB_ReleaseDm(yuv_pipe);
                //RTNA_DBG_Str3("IBC.R\r\n");
                //dbg_printf(3,"IBC buf_addr = 0x%x\r\n", buf_addr);
            }

            MMPF_Video_UpdateWrPtr(yuv_pipe);
            buf_addr = (MMP_ULONG)MMPF_Video_CurWrPtr(yuv_pipe);
        
            pIbcPipeCtl->IBC_ADDR_Y_ST = buf_addr + FRAME_PAYLOAD_HEADER_SZ ;
            pIbcPipeCtl->IBC_ADDR_U_ST = pIbcPipeCtl->IBC_ADDR_Y_ST + yuv_ph->UVC_H264_PH.wImageWidth * yuv_ph->UVC_H264_PH.wImageHeight;
            pIbcPipeCtl->IBC_ADDR_V_ST = pIbcPipeCtl->IBC_ADDR_U_ST + yuv_ph->UVC_H264_PH.wImageWidth * yuv_ph->UVC_H264_PH.wImageHeight >> 1;
            pIbcPipeCtl->IBC_BUF_CFG |= (IBC_STORE_EN);
            
            /*RTNA_DBG_Str(0, "yuv_ph->UVC_H264_PH_LEN.wImageWidth * yuv_ph->UVC_H264_PH.wImageHeight= ");
            RTNA_DBG_Long(0,(MMP_ULONG)(yuv_ph->UVC_H264_PH.wImageWidth * yuv_ph->UVC_H264_PH.wImageHeight));
            RTNA_DBG_Str(0, "\r\n");*/

			//if(bPowerOnWorking){
				if(bFirstFrame)
				{

					bFirstFrame = FALSE;
				}else/* if(bScaning)*/{
		
					MMPF_USBCTL_PostMsg(2,TASK_USB_PRIO,USBCTL_MSG_START_DECODING,0,(void *)(buf_addr+FRAME_PAYLOAD_HEADER_SZ));
				}

        }
        else { //ring buffer mode
            if (release) {
                //MMPF_Timer_Log(&tlRd0); //For single YUY2
                DBG_SMALL_TAG("W");//'W'rite IBC buffer
                MMPF_USB_ReleaseDm(0);
            } else {
                DBG_SMALL_TAG("N");//'N'ot release Dm
            }
        }

    } else {
    
        //RTNA_DBG_Str3("->\r\n");
       //MMPF_USB_ReleaseDm();
    }

#if (SUPPORT_OSD_FUNC)
    if(intsrc0 & IBC_INT_PRE_FRM_RDY) {
        if(stream_cfg->pipe_en&PIPE0_EN) {
            if(pipe0_cfg==PIPE_CFG_H264) {
                //dbg_printf(3, "=PreRdy(0)=\r\n");   
                MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_IBC0_PRERDY, MMPF_OS_FLAG_SET); 
            }
        }
    }

    if(intsrc1 & IBC_INT_PRE_FRM_RDY) {
        if(stream_cfg->pipe_en&PIPE1_EN) {
            //if(pipe1_cfg==PIPE_CFG_H264) {
            if(gbCurH264Type==FRAMEBASE_H264) {
                //dbg_printf(3, "=PreRdy(1)=\r\n");   
                MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_IBC1_PRERDY, MMPF_OS_FLAG_SET); 
            }
        }
    }
#endif

	if (intsrc0 & IBC_INT_FRM_END) {
	}

	if (intsrc1 & IBC_INT_FRM_END) {
    #if DBG_H264
	    DBG_S(1, " IE ");//IBC End
	#endif
	}
    if (intsrc2 & IBC_INT_FRM_END) {
    }

	if (intsrc0 & IBC_INT_FRM_ST) {
	    if (IS_PIPE_RING(stream_cfg, 0)) {
	        MMPF_Timer_Log(&tlWr0S);
			DBG_SMALL_TAG("S");
	    }
	    if (CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_0]) {
	        IbcCallBackFunc *Callback = CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_0];
	        CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_0] = NULL;
	        Callback();
	    }
	}
	if (intsrc1 & IBC_INT_FRM_ST) {
	    if (CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_1]) {
	        IbcCallBackFunc *Callback = CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_1];
	        CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_1] = NULL;
	        Callback();
	    }
	}
	#if DRAM_SIZE > 2
	if (intsrc2 & IBC_INT_FRM_ST) {
	    if (CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_2]) {
	        IbcCallBackFunc *Callback = CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_2];
	        CallBackFuncIbc[MMPF_IBC_EVENT_FRM_ST][MMPF_IBC_PIPE_2] = NULL;
	        Callback();
	    }
	}
	#endif

	#endif //#if	defined(ALL_FW)
	
	
	//KK_Debug4("DBK");
	
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_LoobackYUVFrame
//  Description : 
//------------------------------------------------------------------------------
void MMPF_Display_LoobackYUVFrame(MMPF_GRAPHICS_RECT *Rect,
                                  GraphicRotDMACallBackFunc *GraEndCallback,
                                  MMP_ULONG SrcAddr,
                                  MMP_UBYTE ubSrcIBCPipeNum)
{
    MMP_ERR    ret;
    MMP_USHORT usPxlDly = 2;
    MMPF_GRAPHICS_BUFATTRIBUTE  dummy;
    MMPF_SCALER_PATH            scalp = MMPF_SCALER_PATH_2; 
    MMPF_SCALER_FIT_RANGE       ftrge;
    MMPF_SCALER_GRABCONTROL     grctl;
    MMPF_IBC_PIPEATTRIBUTE      IbcAttr;

    MMPF_Scaler_SetPath(MMPF_SCALER_SOURCE_GRA, MMPF_SCALER_PATH_2);  // gra -> scaler 2
    MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH_2, MMP_FALSE, MMPF_SCALER_COLRMTX_BT601);

    m_GraSrcBufAttr.usWidth      = PIPE_INFO(ubSrcIBCPipeNum, w);
    m_GraSrcBufAttr.usHeight     = PIPE_INFO(ubSrcIBCPipeNum, h);
    m_GraSrcBufAttr.usLineOffset = m_GraSrcBufAttr.usWidth;
    m_GraSrcBufAttr.colordepth   = MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE;
    m_GraSrcBufAttr.ulBaseAddr   = SrcAddr;
    m_GraSrcBufAttr.ulBaseUAddr  = SrcAddr + ALIGN16(m_GraSrcBufAttr.usWidth) * ALIGN16(m_GraSrcBufAttr.usHeight);
    m_GraSrcBufAttr.ulBaseVAddr  = m_GraSrcBufAttr.ulBaseUAddr + (ALIGN16(m_GraSrcBufAttr.usWidth)*ALIGN16(m_GraSrcBufAttr.usHeight)/4);

    if (Rect == NULL) {
        m_GraRect.usWidth           = m_GraSrcBufAttr.usWidth;
        m_GraRect.usHeight          = m_GraSrcBufAttr.usHeight;
        m_GraRect.usLeft            = 0;
        m_GraRect.usTop             = 0;
    }
    else {
        m_GraRect = *Rect;
    }

    ret = MMPF_Graphics_SetScaleAttribute (&m_GraSrcBufAttr, &m_GraRect, 1, MMPF_GRAPHICS_SCAL_FB);

    if (ret != MMP_ERR_NONE) {
        return;
    }

    dummy.ulBaseAddr = 0;
    
    ftrge.usFitResol  = 30;
    ftrge.fitmode     = MMPF_SCALER_FITMODE_OUT;
    ftrge.usInWidth   = m_GraRect.usWidth;
    ftrge.usInHeight  = m_GraRect.usHeight;
    ftrge.usOutWidth  = 320;
    ftrge.usOutHeight = 180;

    IbcAttr.function      = MMPF_IBC_FX_TOFB;
    IbcAttr.ulBaseAddr    = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_G) + FRAME_PAYLOAD_HEADER_SZ;
    IbcAttr.ulBaseUAddr   = IbcAttr.ulBaseAddr + 320 * 180;
    IbcAttr.ulBaseVAddr   = IbcAttr.ulBaseUAddr + 320 * 180;
    IbcAttr.colorformat   = MMPF_IBC_COLOR_NV12;
    IbcAttr.bMirrorEnable = 0;
    IbcAttr.usMirrorWidth = 0;
    IbcAttr.ulLineOffset  = 0;
    IbcAttr.InputSource   = MMPF_ICO_PIPE_2;
    MMPF_IBC_SetAttributes(MMPF_IBC_PIPE_2 , &IbcAttr);

    MMPF_Scaler_SetEngine(MMP_FALSE, scalp, &ftrge, &grctl);
    MMPF_Scaler_SetLPF(scalp, &ftrge, &grctl);
    MMPF_Scaler_SetOutputColor(scalp, MMP_FALSE, MMPF_SCALER_COLRMTX_BT601);

    if (grctl.usScaleN > grctl.usScaleM) {
        MMPF_Scaler_SetPixelLineDelay(scalp, 2, 0);
    }
    else {
        usPxlDly = 1;
        MMPF_Scaler_SetPixelLineDelay(scalp, 0, 0);
    }

    if (gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG)
    {
        usPxlDly = 2;
        if (grctl.usScaleN > grctl.usScaleM) {
            usPxlDly = 2;
            MMPF_Scaler_SetPixelLineDelay(scalp, 0, 0x88); 
        }
        else {
            if(m_GraRect.usWidth <= 160){
                usPxlDly = 6;
            }
            else if(m_GraRect.usWidth <= 320){
                usPxlDly = 4;
            }
            else if(m_GraRect.usWidth <= 800){
                usPxlDly = 2;
            }
            else{
                usPxlDly = 1;
            }
            //usPxlDly = (m_GraRect.usWidth <= 800) ? (2):(1);
            MMPF_Scaler_SetPixelLineDelay(scalp, 0, 0);
        }
    }

    MMPF_IBC_SetStoreEnable(MMPF_IBC_PIPE_2, MMP_TRUE);
    MMPF_IBC_SetInterruptEnable(MMPF_IBC_PIPE_2, MMPF_IBC_EVENT_FRM_RDY, MMP_TRUE);

    gljpeg_en_start_time = MMPF_BSP_GetTick();

    ret = MMPF_Graphics_Scale(m_GraSrcBufAttr, dummy, GraEndCallback, usPxlDly, 0xFFFF, MMPF_IBC_PIPE_2);
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_LoobackMJPEGFrame
//  Description : 
//------------------------------------------------------------------------------
void MMPF_Display_LoobackMJPEGFrame(MMPF_GRAPHICS_RECT 			*Rect,
                                    GraphicRotDMACallBackFunc 	*GraEndCallback,
                                    MMP_ULONG                   SrcAddr,
                                    MMP_UBYTE  					ubSrcIBCPipeNum)
{
	AITPS_JPG					pJPG = AITC_BASE_JPG;
	AITPS_AIC					pAIC = AITC_BASE_AIC;
    MMP_ERR     				ret;
    MMP_USHORT  				usPxlDly = 2;
    MMPF_GRAPHICS_BUFATTRIBUTE 	dummy;
    MMPF_SCALER_PATH        	scalp = MMPF_SCALER_PATH_2;
    MMPF_SCALER_FIT_RANGE   	ftrge;
    MMPF_SCALER_GRABCONTROL 	grctl;
    MMPF_IBC_PIPEATTRIBUTE  	IbcAttr;
	
    #if XU_FRAMEBASE_CAPTURE
    extern RES_TYPE_LIST FB_s2_res;
    extern MMP_ULONG Cap_jpeg;
    extern MMP_UBYTE gbSkypeMode;
    extern MMP_USHORT Q_Level;
    if((!ubSrcIBCPipeNum)&&(Cap_jpeg==1)) {
        ChangeMJEEG_SnapshotResolution(FB_s2_res, 1);//Capture
        /* A <-> B */
        FB_s2_res = gFramebaseCap.CapResol + FB_s2_res;
        gFramebaseCap.CapResol = FB_s2_res - gFramebaseCap.CapResol;
        FB_s2_res = FB_s2_res - gFramebaseCap.CapResol;
        /* A <-> B */
        Q_Level = gFramebaseCap.orgMJPG_Quality + Q_Level;
        gFramebaseCap.orgMJPG_Quality = Q_Level - gFramebaseCap.orgMJPG_Quality;
        Q_Level = Q_Level - gFramebaseCap.orgMJPG_Quality;
        Cap_jpeg = 2;
    } else if(ubSrcIBCPipeNum&&(Cap_jpeg==4)){
        ChangeMJEEG_SnapshotResolution(FB_s2_res, 0);//Loopback
        Cap_jpeg = 0;
    } else if((!ubSrcIBCPipeNum)&&(Cap_jpeg==5)) {
        MMP_USHORT tmp;
        Cap_jpeg = 2;
        tmp = Q_Level;
        if(gFramebaseCap.orgMJPG_Quality != 2) {
            gFramebaseCap.orgMJPG_Quality++;
            Q_Level = gFramebaseCap.orgMJPG_Quality;
        }
        ChangeMJEEG_SnapshotResolution(gFramebaseCap.CapResol, 1);//Capture
        Q_Level = tmp;
    }
    if(ubSrcIBCPipeNum&&(gbSkypeMode==0x86)) {
        glGraphicLoopBackCnt = 0;
        return;
    }
    #endif

    MMPF_Scaler_SetPath(MMPF_SCALER_SOURCE_GRA, MMPF_SCALER_PATH_2);  // gra -> scaler 2
#if (CUSTOMER == ANW)
    if(gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG){
    MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH_2, MMP_TRUE, MMPF_SCALER_COLRMTX_EXTEND_BT601);
    }else
#endif
    MMPF_Scaler_SetOutputColor(MMPF_SCALER_PATH_2, MMP_FALSE, MMPF_SCALER_COLRMTX_FULLRANGE);

    m_GraSrcBufAttr.usWidth      = PIPE_INFO(ubSrcIBCPipeNum, w);
    m_GraSrcBufAttr.usHeight     = ALIGN8(PIPE_INFO(ubSrcIBCPipeNum, h));
    m_GraSrcBufAttr.usLineOffset = m_GraSrcBufAttr.usWidth;
    m_GraSrcBufAttr.colordepth   = MMPF_GRAPHICS_COLORDEPTH_YUV420_INTERLEAVE;
    m_GraSrcBufAttr.ulBaseAddr   = SrcAddr;
    m_GraSrcBufAttr.ulBaseUAddr  = SrcAddr + ALIGN16(m_GraSrcBufAttr.usWidth) * ALIGN16(m_GraSrcBufAttr.usHeight);
    m_GraSrcBufAttr.ulBaseVAddr  = m_GraSrcBufAttr.ulBaseUAddr + (ALIGN16(m_GraSrcBufAttr.usWidth)*ALIGN16(m_GraSrcBufAttr.usHeight)/4);

    if (Rect == NULL) {
        m_GraRect.usWidth           = m_GraSrcBufAttr.usWidth;
        m_GraRect.usHeight          = m_GraSrcBufAttr.usHeight;
        m_GraRect.usLeft            = 0;
        m_GraRect.usTop             = 0;
    }
    else {
        m_GraRect = *Rect;
    }
    
    ret = MMPF_Graphics_SetScaleAttribute (&m_GraSrcBufAttr, &m_GraRect, 1, MMPF_GRAPHICS_SCAL_FB);
    
    if (ret != MMP_ERR_NONE) {
        return;
    }
    
    dummy.ulBaseAddr = 0;
    
    ftrge.usFitResol = 30;
    ftrge.fitmode    = MMPF_SCALER_FITMODE_OUT;
    ftrge.usInWidth  = m_GraRect.usWidth;
    ftrge.usInHeight = ALIGN8(m_GraRect.usHeight);
    ftrge.usOutWidth = PIPE_INFO(2, w);
    ftrge.usOutHeight= ALIGN8(PIPE_INFO(2, h));

    IbcAttr.function 		= MMPF_IBC_FX_JPG;
    IbcAttr.ulBaseAddr 		= IbcAttr.ulBaseUAddr = IbcAttr.ulBaseVAddr = 0;
    IbcAttr.colorformat 	= MMPF_IBC_COLOR_YUV422;
    IbcAttr.bMirrorEnable 	= 0;
    IbcAttr.usMirrorWidth 	= 0;
    IbcAttr.ulLineOffset 	= 0;
    IbcAttr.InputSource 	= MMPF_ICO_PIPE_2;
    MMPF_IBC_SetAttributes(MMPF_IBC_PIPE_2 , &IbcAttr);
	
    MMPF_Scaler_SetEngine(MMP_FALSE, scalp, &ftrge, &grctl);
    MMPF_Scaler_SetLPF(scalp, &ftrge, &grctl);
#if (CUSTOMER == ANW)
    if(gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG){
    //MMPF_Scaler_SetOutputColor(scalp, MMP_TRUE, MMPF_SCALER_COLRMTX_EXTEND_BT601);
    }else
#endif
	MMPF_Scaler_SetOutputColor(scalp, MMP_FALSE, MMPF_SCALER_COLRMTX_FULLRANGE);

    if (grctl.usScaleN > grctl.usScaleM) {
        MMPF_Scaler_SetPixelLineDelay(scalp, 2, 0);
    }
    else {
        usPxlDly = 1;
        MMPF_Scaler_SetPixelLineDelay(scalp, 0, 0);
    }

    if ((gbCurH264Type == FRAMEBASE_DUAL_H264) || (gbCurH264Type == FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG)) 
    {
		usPxlDly = 2;
        if (grctl.usScaleN > grctl.usScaleM) {
            usPxlDly = 2;
            MMPF_Scaler_SetPixelLineDelay(scalp, 0, 0x88); 
        }
        else {
            if(m_GraRect.usWidth <= 160){
                usPxlDly = 10;
            }
            else if(m_GraRect.usWidth <= 320){
                usPxlDly = 4;
            }
            else if(m_GraRect.usWidth <= 800){
                usPxlDly = 2;
            }
            else{
                usPxlDly = 1;
            }
            //usPxlDly = 1;//(m_GraRect.usWidth <= 800) ? (2):(1);
            MMPF_Scaler_SetPixelLineDelay(scalp, 0, 0);
        }
    }

	RTNA_AIC_Open(pAIC, AIC_SRC_JPG, jpg_isr_a,
					AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3);
	RTNA_AIC_IRQ_En(pAIC, AIC_SRC_JPG);

	pJPG->JPG_INT_CPU_SR = JPG_INT_ENC_DONE;
	pJPG->JPG_INT_CPU_EN = JPG_INT_ENC_DONE;

	pJPG->JPG_CTL |= JPG_ENC_EN;

    gljpeg_en_start_time = MMPF_BSP_GetTick();

    ret = MMPF_Graphics_Scale (m_GraSrcBufAttr, dummy, GraEndCallback, usPxlDly, 0xFFFF, MMPF_IBC_PIPE_2);
}

#if (defined(ALL_FW)&&(PCAM_EN==0))
//------------------------------------------------------------------------------
//  Function    : MMPF_Display_SetRefresh
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_SetRefresh(MMPF_DISPLAY_CONTROLLER controller)
{
	AITPS_DSPY   pDSPY    = AITC_BASE_DSPY;
	AITPS_GBL    pGBL     = AITC_BASE_GBL;

    if (controller == MMPF_DISPLAY_SCD_CONTROL) {
		
    	switch ((pDSPY->DSPY_CTL_2 & DSPY_SCD_SEL_MASK) >> DSPY_SCD_SEL_SHIFT) {
    	case DSPY_TYPE_PL_LCD:
    		if (!(pDSPY->DSPY_CTL_0 & LCD_BUSY_STS)) {
				pDSPY->DSPY_CTL_0 |= SCD_DSPY_REG_READY;
				pDSPY->DSPY_SCD_CTL |= LCD_FRAME_TX;
    		} 
    		else {
		    	return	MMP_DISPLAY_ERR_LCD_BUSY;
			}
			break;
    	case DSPY_TYPE_SPI_LCD:
    		if (!(pDSPY->DSPY_CTL_0 & LCD_BUSY_STS)) {
				pDSPY->DSPY_CTL_0 |= SCD_DSPY_REG_READY;
				pDSPY->DSPY_SCD_CTL |= LCD_FRAME_TX;
    		}
    		else {
		    	return	MMP_DISPLAY_ERR_LCD_BUSY;
			}
			break;
    	case DSPY_TYPE_RGB_LCD:
    	case DSPY_TYPE_TV:
    		pDSPY->DSPY_CTL_0 |= SCD_DSPY_REG_READY;
    		break;
		}
    }
    else {
        if(pGBL->GBL_CCIR_PIN_CTL & GBL_CCIR_OUTPUT){
            #if (CHIP == P_V2)
            AITPS_CCIR  pCCIR = AITC_BASE_CCIR;
            if(!(pCCIR->CCIR_CAPTURE_FRAME_EN & CCIR_PREVIEW_FRAME_ST)){
                pCCIR->CCIR_CAPTURE_FRAME_EN |= CCIR_PREVIEW_FRAME_ST;
            } else {
                DBG_S3("CCIR is busy\r\n");
                return	MMP_DISPLAY_ERR_LCD_BUSY;
            }
            #endif
        } else {
    	switch ((pDSPY->DSPY_CTL_2 & DSPY_PRM_SEL_MASK) >> DSPY_PRM_SEL_SHIFT) {
    	case DSPY_TYPE_PL_LCD:
    		if (!(pDSPY->DSPY_CTL_0 & LCD_BUSY_STS)) {
				pDSPY->DSPY_CTL_2 |= PRM_DSPY_REG_READY;
				pDSPY->DSPY_CTL_0 |= LCD_FRAME_TX;
    		}
    		else {
		    	return	MMP_DISPLAY_ERR_LCD_BUSY;
			}
			break;
    	case DSPY_TYPE_SPI_LCD:
    		if (!(pDSPY->DSPY_CTL_0 & LCD_BUSY_STS)) {
				pDSPY->DSPY_CTL_2 |= PRM_DSPY_REG_READY;
				pDSPY->DSPY_CTL_0 |= LCD_FRAME_TX;
    		}
    		else {
		    	return	MMP_DISPLAY_ERR_LCD_BUSY;
			}
			break;
    	case DSPY_TYPE_RGB_LCD:
    	case DSPY_TYPE_TV:
    		pDSPY->DSPY_CTL_2 |= PRM_DSPY_REG_READY;
    		break;
		}
		}    		
    }
    return MMP_ERR_NONE;
}
#endif // PCAM_EN==0

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_StartPreview
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_StartPreview(MMP_USHORT usIBCPipe, MMP_BOOL bCheckFrameEnd)
{
    AITPS_IBC   pIBC    = AITC_BASE_IBC;
    volatile AITPS_IBCP  pIbcPipeCtl;
    MMP_BOOL    bVifEn = MMP_FALSE;

	gsPreviewPath |= (1 << usIBCPipe);

    if (usIBCPipe == 0) {
        pIbcPipeCtl = &(pIBC->IBCP_0);
    }
    else if (usIBCPipe == 1) {
        pIbcPipeCtl = &(pIBC->IBCP_1);
    }
    else {
        pIbcPipeCtl = &(pIBC->IBCP_2);
    }

    //m_bReceiveStopPreviewSig[usIBCPipe] = MMP_FALSE;
	
    if (gbPreviewBufferCount[usIBCPipe]) {
        MMPF_Display_StartSoftwareRefresh(usIBCPipe); 
        dbg_printf(0, "  ***** IBC%d Start Preview ***** \r\n", usIBCPipe);
        pIbcPipeCtl->IBC_ADDR_Y_ST = glPreviewBufAddr[usIBCPipe][0];
    	pIbcPipeCtl->IBC_ADDR_U_ST = glPreviewUBufAddr[usIBCPipe][0];
        pIbcPipeCtl->IBC_ADDR_V_ST = glPreviewVBufAddr[usIBCPipe][0];
    #if (SUPPORT_OSD_FUNC)
        MMPF_IBC_SetInterruptEnable(usIBCPipe, MMPF_IBC_EVENT_FRM_PRERDY, MMP_TRUE);
    #endif
        MMPF_IBC_SetInterruptEnable(usIBCPipe, MMPF_IBC_EVENT_FRM_RDY, MMP_TRUE);
        MMPF_IBC_SetInterruptEnable(usIBCPipe, MMPF_IBC_EVENT_FRM_END, MMP_TRUE);
        MMPF_IBC_SetStoreEnable(usIBCPipe, MMP_TRUE);
    }
    else {
    #if DBG_H264
        MMPF_IBC_SetInterruptEnable(usIBCPipe, MMPF_IBC_EVENT_FRM_END, MMP_TRUE);
    #endif
    }

	#if defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)||(SENSOR_EN)
	gsSensorFunction->MMPF_Sensor_Set3AStatus(MMP_TRUE);
	#endif		

	// Enable VIF input
	#if (defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
	MMPF_VIF_IsInterfaceEnable (&bVifEn);
	if (bVifEn == MMP_FALSE) {
	    MMPF_VIF_EnableInputInterface(MMP_TRUE);
	}
	#endif

    #if 0
	if (bCheckFrameEnd) {
		m_bStartPreviewFrameEndSig = MMP_TRUE;
		if (MMPF_OS_AcquireSem(m_StartPreviewFrameEndSem, 10000)) {
			RTNA_DBG_Str(0, "Wait IBC frame end :Fail\r\n");
			return MMP_DISPLAY_ERR_FRAME_END;
		}	
	}
    #endif

    return MMP_ERR_NONE;
 }

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_StopPreview
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_StopPreview(MMP_USHORT usIBCPipe)
{
	AITPS_IBC   pIBC    = AITC_BASE_IBC;

	//RTNA_DBG_Str(0, "=== MMPF_Display_StopPreview start ===\r\n");

	if (gsPreviewPath == 0)
		return MMP_ERR_NONE;

    if (usIBCPipe == 0) {
    #if (SUPPORT_OSD_FUNC)
        pIBC->IBC_P0_INT_CPU_EN &= ~IBC_INT_PRE_FRM_RDY;
    #endif
        pIBC->IBC_P0_INT_CPU_EN &= ~IBC_INT_FRM_RDY;
		gsPreviewPath &= ~(1 << usIBCPipe);
    }
    else if (usIBCPipe == 1) {
    #if (SUPPORT_OSD_FUNC)
        pIBC->IBC_P1_INT_CPU_EN &= ~IBC_INT_PRE_FRM_RDY;
    #endif
        pIBC->IBC_P1_INT_CPU_EN &= ~IBC_INT_FRM_RDY;
		gsPreviewPath &= ~(1 << usIBCPipe);
    }
    else  {
        pIBC->IBC_P2_INT_CPU_EN &= ~IBC_INT_FRM_RDY;
		gsPreviewPath &= ~(1 << usIBCPipe);
    }

    #if 0//LCD_DISPLAY_ON==1
    if (m_bReceiveStopPreviewSig[usIBCPipe] == MMP_TRUE)
		return MMP_ERR_NONE;
    else {
        m_bReceiveStopPreviewSig[usIBCPipe] = MMP_TRUE;
        MMPF_OS_AcquireSem(m_PreviewControlSem, 0);
	}
    #endif

	RTNA_DBG_Str(0, "=== MMPF_Display_StopPreview end ===\r\n");

    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_StartSoftwareRefresh
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_StartSoftwareRefresh(MMP_USHORT usIBCPipe)
{
	// even odd toggle bit
	if (gbPreviewBufferCount[usIBCPipe]) {
	    gbExposureDoneFrame[usIBCPipe] = gbPreviewBufferCount[usIBCPipe] - 1;
	}
	else {
	    gbExposureDoneFrame[usIBCPipe] = 0;
	}
	
	gbCurIBCBuf[usIBCPipe] = 0;

	return MMP_ERR_NONE;
}
#if LCD_DISPLAY_ON==1

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_StartFLMRefresh
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_StartFLMRefresh(void)
{
	AITPS_GPIO	pGPIO   = AITC_BASE_GPIO;
    AITPS_AIC   pAIC 	= AITC_BASE_AIC;
    
	MMP_ULONG	gpio_shift, gpio_group;

    gbExposureDone = 0;

#if defined(TARGET_ID_170201)
   	ait81x_tc_open(&TC2_DESC, TC_CPCTRG | TC_CLKS_MCK8);
	ait81x_tc_write(&TC2_DESC, RC, 21000);

	ait81x_irq_open(TC2_DESC.periph_id, AIC_DIRECT_TO_IRQ, 0,
					AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE,timer2_asm_irq_handler);
#endif

	// Enable FLM <-> GPIO interrupt.
	gpio_shift = FLM_GPIO_NUM;
	gpio_group = 0;
	while (gpio_shift >= 32) {
		gpio_shift -= 32;
		gpio_group += 1;
	}
			
    pGPIO->GPIO_EN[gpio_group] &= ~(1 << gpio_shift);
    pGPIO->GPIO_INT_L2H_EN[gpio_group] |= (1 << gpio_shift);
   	pGPIO->GPIO_INT_H2L_EN[gpio_group] &= ~(1 << gpio_shift);

    pGPIO->GPIO_INT_L2H_STS[gpio_group] = (1 << gpio_shift);
   	pGPIO->GPIO_INT_CPU_EN[gpio_group] |= (1 << gpio_shift);

    RTNA_AIC_Open(pAIC, AIC_SRC_GPIO, gpio_isr_a,
                AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3);
	RTNA_AIC_IRQ_En(pAIC, AIC_SRC_GPIO);
    
    // clear exposure done flag
    gbExposureDone = 0;

	return	MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_StopFLMRefresh
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_StopFLMRefresh(void)
{
    AITPS_AIC   pAIC 	= AITC_BASE_AIC;

#if defined(TARGET_ID_170201)
	ait81x_irq_close(TC2_DESC.periph_id);
	ait81x_tc_close(&TC2_DESC);
#endif

	RTNA_AIC_IRQ_Dis(pAIC, AIC_SRC_GPIO);

	// Check if LCD is busy.
	return	MMP_ERR_NONE;
}
#endif

//------------------------------------------------------------------------------
//  Function    : MMPF_Display_FrameDoneTrigger
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_FrameDoneTrigger(MMP_USHORT usIBCPipe)
{
	#if	defined(ALL_FW) 
    AITPS_IBC   pIBC    = AITC_BASE_IBC;
    volatile AITPS_IBCP pIbcPipeCtl;

    if (usIBCPipe == 0) {
        pIbcPipeCtl = &(pIBC->IBCP_0);
    }
    else if (usIBCPipe == 1) {
        pIbcPipeCtl = &(pIBC->IBCP_1);
    }
    else {
        pIbcPipeCtl = &(pIBC->IBCP_2);
    }

	if (gIBCLinkType[usIBCPipe] & MMPF_IBC_LINK_VIDEO) {
#if USB_FRAMEBASE_DUAL_H264_STREAM
        if((gbCurH264Type==FRAMEBASE_DUAL_H264) || (gbCurH264Type==FRAMEBASE_DUAL_H264_MJPEG) || (gbCurH264Type == FRAMEBASE_H264FRAME_MJPEG))
        MMPF_VIDENC_TriggerFrameDone(usIBCPipe,
                                    &(gbExposureDoneFrame[usIBCPipe]),
                                    &(gbCurIBCBuf[usIBCPipe]),
                                    gbPreviewBufferCount[usIBCPipe],
                                    glPreviewBufAddr[usIBCPipe],
                                    glPreviewUBufAddr[usIBCPipe],
                                    glPreviewVBufAddr[usIBCPipe]);
        else
#endif
        MMPF_VIDENC_TriggerFrameDone(0,
                                    &(gbExposureDoneFrame[usIBCPipe]),
                                    &(gbCurIBCBuf[usIBCPipe]),
                                    gbPreviewBufferCount[usIBCPipe],
                                    glPreviewBufAddr[usIBCPipe],
                                    glPreviewUBufAddr[usIBCPipe],
                                    glPreviewVBufAddr[usIBCPipe]);
	}
	else {
    	gbExposureDoneFrame[usIBCPipe] += 1;
    	if (gbExposureDoneFrame[usIBCPipe] >= gbPreviewBufferCount[usIBCPipe]) {
    		gbExposureDoneFrame[usIBCPipe] = 0;
        }
    	gbCurIBCBuf[usIBCPipe] += 1;
    	if (gbCurIBCBuf[usIBCPipe] >= gbPreviewBufferCount[usIBCPipe]) {
    		gbCurIBCBuf[usIBCPipe] = 0;
        }
    }

    #if (defined(ALL_FW)&&(PCAM_EN==0))
    if (gIBCLinkType[usIBCPipe] & MMPF_IBC_LINK_ROTATE) {
        gsIBCtoDMAPipe = usIBCPipe;
        if (gbInFDTCMode && gbFWDrawFaceRect) {
            MMPF_FDTC_SetCurPreviewBufAddr(glPreviewBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]],
            				               glPreviewUBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]],
            				               glPreviewVBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
            MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_FDTC_DRAWRECT, MMPF_OS_FLAG_SET);
        }
        else
        // set os flag to sensor task, which is responsible to operate rotate DMA
        MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_ROTDMA, MMPF_OS_FLAG_SET);
    }
	if (gIBCLinkType[usIBCPipe] & MMPF_IBC_LINK_DISPLAY) {
        if (gbInFDTCMode && gbFWDrawFaceRect) {
            MMPF_FDTC_SetCurPreviewBufAddr(glPreviewBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]],
            				               glPreviewUBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]],
            				               glPreviewVBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
            MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_FDTC_DRAWRECT, MMPF_OS_FLAG_SET);
        }
        else
       	if (gPreviewMode[usIBCPipe] == MMPF_DISPLAY_P_LCD || 
       		gPreviewMode[usIBCPipe] == MMPF_DISPLAY_TV || 
       		gPreviewMode[usIBCPipe] == MMPF_DISPLAY_RGB_LCD ||
       		gPreviewMode[usIBCPipe] == MMPF_DISPLAY_HDMI ||
       		gPreviewMode[usIBCPipe] == MMPF_DISPLAY_CCIR) {
    		if (!(pDSPY->DSPY_CTL_0 & LCD_BUSY_STS) || gPreviewMode[usIBCPipe] == MMPF_DISPLAY_CCIR) {
	        	MMPF_Display_SetWinAddr(gPreviewWinID[usIBCPipe], 
       					glPreviewBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]],
    					glPreviewUBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]],
   						glPreviewVBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
				MMPF_Display_SetWinActive(gPreviewWinID[usIBCPipe], MMP_TRUE);	        						

   	        	if (gPreviewWinID[usIBCPipe] == MMPF_DISPLAY_WIN_SCD_WIN) {
   		    	    MMPF_Display_SetRefresh(MMPF_DISPLAY_SCD_CONTROL);
        	    }
               	else {
   	    		    MMPF_Display_SetRefresh(MMPF_DISPLAY_PRM_CONTROL);
           	    }
	        }
        }
	   	else if (gPreviewMode[usIBCPipe] == MMPF_DISPLAY_FLM) {
    		gbExposureDone = 1;
		}
	}

    if (gIBCLinkType[usIBCPipe] & MMPF_IBC_LINK_GRAPHIC) {
        MMPF_GRAPHICS_BUFATTRIBUTE src, dst;

        dst.ulBaseAddr = (dst.ulBaseUAddr = (dst.ulBaseVAddr = 0));
        src.ulBaseAddr = glPreviewBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]];
        src.ulBaseUAddr = (src.ulBaseVAddr = 0);

        if (pIbcPipeCtl->IBC_SRC_SEL & IBC_SRC_YUV420) {
            src.colordepth = MMPF_GRAPHICS_COLORDEPTH_YUV420;
            src.ulBaseUAddr = glPreviewUBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]];
            src.ulBaseVAddr = glPreviewVBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]];
        }
        else {
            src.colordepth = MMPF_GRAPHICS_COLORDEPTH_YUV422;
        }
        MMPF_Graphics_Scale(src, dst, NULL);
    }
    #endif

    //for face detection
    #if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
    if (gIBCLinkType[usIBCPipe] & MMPF_IBC_LINK_FDTC) {
    	if (MMPF_FDTC_GetFaceDeteState() == MMPF_FDTC_ACTIVE_STATE) {
            MMPF_FDTC_SetFaceDetectInputSrc(glPreviewBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
            MMPF_OS_SetFlags(FDTC_Flag, FLAG_FDTC_DMACOPY, MMPF_OS_FLAG_SET);
    	}
    }
    #endif // PCAM_EN==0

	pIbcPipeCtl->IBC_ADDR_Y_ST = glPreviewBufAddr[usIBCPipe][gbCurIBCBuf[usIBCPipe]];
	pIbcPipeCtl->IBC_ADDR_U_ST = glPreviewUBufAddr[usIBCPipe][gbCurIBCBuf[usIBCPipe]];
	pIbcPipeCtl->IBC_ADDR_V_ST = glPreviewVBufAddr[usIBCPipe][gbCurIBCBuf[usIBCPipe]];

	#endif //
    return MMP_ERR_NONE;
}
#if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
//------------------------------------------------------------------------------
//  Function    : MMPF_Display_RotateFrameDone
//  Description : Callback function for rotate DMA done
//------------------------------------------------------------------------------
#if (defined(ALL_FW)&&(PCAM_EN==0))
void MMPF_Display_RotateFrameDone(void)
{ 
    AITPS_DSPY  pDSPY   = AITC_BASE_DSPY;

    if (gIBCLinkType[gsIBCtoDMAPipe] & MMPF_IBC_LINK_ROTATE) {
       	if (gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_P_LCD || 
       		gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_TV || 
       		gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_RGB_LCD ||
       		gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_HDMI ||
       		gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_CCIR) {
    		if (!(pDSPY->DSPY_CTL_0 & LCD_BUSY_STS) || gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_CCIR) {
	        	MMPF_Display_SetWinAddr(gPreviewWinID[gsIBCtoDMAPipe], glRotateBufAddr[gbRotateDoneBufIdx],
    					glRotateUBufAddr[gbRotateDoneBufIdx], glRotateVBufAddr[gbRotateDoneBufIdx]);
				MMPF_Display_SetWinActive(gPreviewWinID[gsIBCtoDMAPipe], MMP_TRUE);

   	        	if (gPreviewWinID[gsIBCtoDMAPipe] == MMPF_DISPLAY_WIN_SCD_WIN) {
   		    	    MMPF_Display_SetRefresh(MMPF_DISPLAY_SCD_CONTROL);
        	    }
               	else {
   	    		    MMPF_Display_SetRefresh(MMPF_DISPLAY_PRM_CONTROL);
           	    }
	        }
	        gbRotateDoneBufIdx = (gbRotateDoneBufIdx+1)%gbRotateBufferCount;
        }
	   	else if (gPreviewMode[gsIBCtoDMAPipe] == MMPF_DISPLAY_FLM) {
            gbRotateDoneBufIdx = (gbRotateDoneBufIdx+1)%gbRotateBufferCount;
    		gbExposureDone = 1;
		}
	}
}
//------------------------------------------------------------------------------
//  Function    : MMPF_Display_DMARotateImage
//  Description : Use the rotate DMA to rotate image in the framebuffer
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_DMARotateFrame()
{
    AITPS_DSPY pDSPY = AITC_BASE_DSPY;
    MMP_USHORT offset, colordepth;
    MMPF_GRAPHICS_BUFATTRIBUTE srcbufattribute, dstbufattribute;
    MMPF_GRAPHICS_RECT srcrect;
    MMPF_DISPLAY_WINID winID;
    MMP_ERR ret;

    winID = gPreviewWinID[gsIBCtoDMAPipe];
    if (winID != MMPF_DISPLAY_WIN_SCD_WIN && winID != MMPF_DISPLAY_WIN_CCIR) {
        offset = winID * 0x100;

        colordepth = *(MMP_USHORT *)((MMP_ULONG)&(pDSPY->DSPY_MAIN_FMT) + offset);
        switch(colordepth) {
        case WIN_8BPP:
            srcbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_8;
            dstbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_8;
            srcbufattribute.usLineOffset = gsPreviewBufWidth;
            dstbufattribute.usLineOffset = gsPreviewBufHeight;
            break;
        case WIN_16BPP:
            srcbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_16;
            dstbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_16;
            srcbufattribute.usLineOffset = ALIGN32(gsPreviewBufWidth*2);
            dstbufattribute.usLineOffset = ALIGN32(gsPreviewBufHeight*2);
            break;
        case WIN_24BPP:
            srcbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_24;
            dstbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_24;
            srcbufattribute.usLineOffset = gsPreviewBufWidth*3;
            dstbufattribute.usLineOffset = gsPreviewBufHeight*3;
            break;
        case WIN_YUV420:
            srcbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_YUV420;
            dstbufattribute.colordepth = MMPF_GRAPHICS_COLORDEPTH_YUV420;
            srcbufattribute.usLineOffset = gsPreviewBufWidth;
            dstbufattribute.usLineOffset = gsPreviewBufHeight;
            break;
        default:
            return MMP_DISPLAY_ERR_PARAMETER;
        }
        srcbufattribute.usWidth = gsPreviewBufWidth;
        srcbufattribute.usHeight = gsPreviewBufHeight;
        srcbufattribute.ulBaseAddr = glPreviewBufAddr[gsIBCtoDMAPipe][gbExposureDoneFrame[gsIBCtoDMAPipe]];
        srcbufattribute.ulBaseUAddr = glPreviewUBufAddr[gsIBCtoDMAPipe][gbExposureDoneFrame[gsIBCtoDMAPipe]];
        srcbufattribute.ulBaseVAddr = glPreviewVBufAddr[gsIBCtoDMAPipe][gbExposureDoneFrame[gsIBCtoDMAPipe]];
        dstbufattribute.ulBaseAddr = glRotateBufAddr[gbRotateCurBufIdx];
        dstbufattribute.ulBaseUAddr = glRotateUBufAddr[gbRotateCurBufIdx];
        dstbufattribute.ulBaseVAddr = glRotateVBufAddr[gbRotateCurBufIdx];

        srcrect.usLeft = 0;
        srcrect.usTop = 0;
        srcrect.usWidth = gsPreviewBufWidth;
        srcrect.usHeight = gsPreviewBufHeight;

        ret = MMPF_DMA_RotateImageBuftoBuf(&srcbufattribute, &srcrect, &dstbufattribute, 
                                            0, 0, MMPF_GRAPHICS_ROTATE_RIGHT_90, MMPF_Display_RotateFrameDone, MMP_FALSE, MMPF_DMA_R_NO_MIRROR);
        
        if (ret == MMP_ERR_NONE) {
            gbRotateCurBufIdx = (gbRotateCurBufIdx+1)%gbRotateBufferCount;
        }
    }
    return MMP_ERR_NONE;
}
#endif // PCAM_EN==0
#endif
//------------------------------------------------------------------------------
//  Function    : MMPF_Display_SetWinAddr
//  Description : Set window address
//------------------------------------------------------------------------------
#if (defined(ALL_FW)&&(PCAM_EN == 0))
MMP_ERR MMPF_Display_SetWinAddr(MMPF_DISPLAY_WINID winID, MMP_ULONG ulBaseAddr,
                            MMP_ULONG ulBaseUAddr, MMP_ULONG ulBaseVAddr)
{
    AITPS_DSPY	pDSPY = AITC_BASE_DSPY;
    MMP_USHORT	offset;

	if (winID == MMPF_DISPLAY_WIN_SCD_WIN) {
		pDSPY->DSPY_CTL_0 &= ~SCD_DSPY_REG_READY;
		pDSPY->DSPY_SCD_WIN_ADDR_ST = ulBaseAddr;
	}
	else if(winID == MMPF_DISPLAY_WIN_CCIR) {
		AITPS_CCIR pCCIR = AITC_BASE_CCIR;
		#if (CHIP == P_V2)
		if(pCCIR->CCIR_CTL_2 & CCIR_YUV420_MODE_EN) {
		    pCCIR->CCIR_YUV420_Y_ADDR = ulBaseAddr;
		    pCCIR->CCIR_YUV420_U_ADDR = ulBaseUAddr;
            pCCIR->CCIR_YUV420_V_ADDR = ulBaseVAddr;
		} else {
		    MMP_ULONG ulBufSize;
		    ulBufSize = pCCIR->CCIR_PREVIEW_BUF_ED_ADDR - pCCIR->CCIR_PREVIEW_BUF_ST_ADDR;
		    pCCIR->CCIR_PREVIEW_BUF_ST_ADDR = ulBaseAddr;
		    pCCIR->CCIR_PREVIEW_BUF_ED_ADDR = ulBaseAddr + ulBufSize;
		}
		#endif
		//VAR_L(3,pCCIR->CCIR_PREVIEW_BUF_ST_ADDR);
		//VAR_L(3,pCCIR->CCIR_PREVIEW_BUF_ED_ADDR);
	}
	else {
		offset = winID * 0x100;	
		pDSPY->DSPY_CTL_2 &= ~PRM_DSPY_REG_READY;

		*(AIT_REG_D *)((MMP_ULONG)&(pDSPY->DSPY_MAIN_0_ADDR_ST) + offset) = ulBaseAddr;
		*(AIT_REG_D *)((MMP_ULONG)&(pDSPY->DSPY_MAIN_0_U_ADDR_ST) + offset) = ulBaseUAddr;
		*(AIT_REG_D *)((MMP_ULONG)&(pDSPY->DSPY_MAIN_0_V_ADDR_ST) + offset) = ulBaseVAddr;
	}			
    return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_Display_SetWinActive
//  Description : Set window address
//------------------------------------------------------------------------------
MMP_ERR MMPF_Display_SetWinActive(MMPF_DISPLAY_WINID winID, MMP_BOOL bEnable)
{
    AITPS_DSPY	pDSPY = AITC_BASE_DSPY;
    MMP_USHORT	offset;

	if (winID == MMPF_DISPLAY_WIN_SCD_WIN || winID == MMPF_DISPLAY_WIN_CCIR)
		return	MMP_ERR_NONE;
	
	offset = winID * 0x100;	
	if (bEnable)
		*(AIT_REG_D *)((MMP_ULONG)&(pDSPY->DSPY_MAIN_CTL) + offset) |= WIN_EN;
	else
		*(AIT_REG_D *)((MMP_ULONG)&(pDSPY->DSPY_MAIN_CTL) + offset) &= ~WIN_EN;				
    return MMP_ERR_NONE;
}
#endif // PCAM_EN==0

#if TV_EN==1
//------------------------------------------------------------------------------
//  Function    : MMPF_TV_Initialize
//  Description : Initialize TV
//------------------------------------------------------------------------------
MMP_ERR MMPF_TV_Initialize()
{
    AITPS_TV pTV = AITC_BASE_TV;

	pTV->TVENC_SYNC_CTL |= TV_ENC_SYNC_SW_RST;
	
	pTV->TVENC_MODE_CTL =   TV_BLACKER_LEVEL_EN         | 
	                        TV_FULL_WIDTH_OUTPUT_EN     |
	                        TV_SVIDEO_CVBS_EN           | 
	                        TV_OUTPUT_CVBS_MODE         |
                            TV_CHROMA_UPSAMPLE_EN       | 
                            TV_DELAY_INPUT_Y_ONE_PIX_2  | 
                            TV_LUMA_LPF_EN              |
                            TV_CHROMA_LPF_EN;

    pTV->TVENC_DAC_CONFIG = TV_TRIM_MODE_EN             | 
	                        TV_PLUG_DETECT_EN           |
	                        TV_DAS_Y_OUTPUT_ON          | 
	                        TV_DAX_C_OUTPUT_ON; // lack of mystery 0x0F00

	pTV->TVENC_SYNC_CTL &= ~TV_ENC_SYNC_SW_RST; // 0x70A0
	
    return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_TV_Uninitialize
//  Description : Initialize TV
//------------------------------------------------------------------------------
MMP_ERR MMPF_TV_Uninitialize(void)
{
    AITPS_TV pTV = AITC_BASE_TV;

	pTV->TVIF_DAC_IF_1ST_CTL = 0;
	pTV->TVENC_MODE_CTL = pTV->TVENC_MODE_CTL | 0x1;
    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_TV_ColorBar
//  Description : Color bar test
//------------------------------------------------------------------------------
MMP_ERR MMPF_TV_ColorBar(MMPF_TV_TYPE TVtype)
{
    #if (CHIP == P_V2)
    AITPS_TV pTV = AITC_BASE_TV;
    #endif

	#if (CHIP == P_V2)
	pTV->TVIF_IF_EN = (TVtype) ? (0x41 | TV_TYPE_PAL) : 0x41;
	pTV->TVIF_DAC_IF_1ST_CTL = 0x0c;
	pTV->TVENC_SYNC_CTL = pTV->TVENC_SYNC_CTL | 0xC0000000;
	pTV->TVENC_SYNC_CTL = pTV->TVENC_SYNC_CTL & ~0xC0000000;
	pTV->TVENC_MODE_CTL = 0x58060102;
	pTV->TVENC_DAC_CONFIG = 0x000020F0;
	pTV->TVENC_Y_SCALE_CTL = 0x00060062;
	#endif
    return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_TV_EncRegSet
//  Description : General function for setting TV encoder register
//------------------------------------------------------------------------------
MMP_ERR MMPF_TV_EncRegSet(MMP_ULONG ulAddr, MMP_ULONG ulData)
{
	AIT_REG_D *TVENC_BASE_D = (AIT_REG_D *)0x80000000;

	TVENC_BASE_D[ulAddr] = ulData;
    return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_TV_EncRegGet
//  Description : General function for getting TV encoder register
//------------------------------------------------------------------------------
MMP_ERR MMPF_TV_EncRegGet(MMP_ULONG ulAddr, MMP_ULONG *ulData)
{
	AIT_REG_D *TVENC_BASE_D = (AIT_REG_D *)0x80000000;

	*ulData = TVENC_BASE_D[ulAddr];
    return MMP_ERR_NONE;
}
#endif
